#pragma once

#include "../pilas/TPilaDinamica.h"
#include <math.h>

template<class TElem>
class TSecuenciaDinamicaP
{
public:
	TSecuenciaDinamicaP();
	TSecuenciaDinamicaP(const TSecuenciaDinamicaP<TElem>&);
	~TSecuenciaDinamicaP();
	TSecuenciaDinamicaP<TElem>& operator=(const TSecuenciaDinamicaP<TElem>&);

	// Operaciones de las secuencias:
	void inserta(const TElem&);
	void borra() throw (EAccesoIndebido);
	const TElem& actual() const throw (EAccesoIndebido);
	void avanza() throw (EAccesoIndebido);
	void reinicia();

	bool esFin() const;
	bool esVacio() const;

	void retrocede() throw (EAccesoIndebido);
private:
	// Operaciones privadas:
	void libera();
	void copia(const TSecuenciaDinamicaP<TElem>&);

private:
	TPilaDinamica<TElem>* _pila1;
	TPilaDinamica<TElem>* _pila2;
};
	template<class TElem>
	TSecuenciaDinamicaP<TElem>::TSecuenciaDinamicaP()
	{
		_pila1 = new TPilaDinamica<TElem>();
		_pila2 = new TPilaDinamica<TElem>();
	}

	template<class TElem>
	TSecuenciaDinamicaP<TElem>::TSecuenciaDinamicaP(const TSecuenciaDinamicaP<TElem>& secuencia)
	{
		_pila1 = new TPilaDinamica<TElem>(secuencia._pila1);
		_pila2 = new TPilaDinamica<TElem>(secuencia._pila2);
	}

	template<class TElem>
	TSecuenciaDinamicaP<TElem>::~TSecuenciaDinamicaP()
	{
		libera();
	}

	template<class TElem>
	TSecuenciaDinamicaP<TElem>& TSecuenciaDinamicaP<TElem>::operator=(const TSecuenciaDinamicaP<TElem>& secuencia)
	{
		if(this != &secuencia)
		{
			libera();
			copia(secuencia);
		}

		return *this;
	}

	// Operaciones de las secuencias:
	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::inserta(const TElem& elem)
	{
		_pila2->apila(elem);
	}

	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::borra() throw (EAccesoIndebido)
	{
		if(esFin())
			throw EAccesoIndebido();

		_pila1->desapila();
	}

	template<class TElem>
	const TElem& TSecuenciaDinamicaP<TElem>::actual() const throw (EAccesoIndebido)
	{
		if(esFin())
			throw EAccesoIndebido();

		return _pila1->cima();
	}

	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::avanza() throw (EAccesoIndebido)
	{
		if(esFin())
			throw EAccesoIndebido();

		_pila2->apila(_pila1->cima());
		_pila1->desapila();
	}

	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::reinicia()
	{
		while(!_pila2->esVacio())
		{
			_pila1->apila(_pila2->cima());
			_pila2->desapila();
		}
	}

	template<class TElem>
	bool TSecuenciaDinamicaP<TElem>::esFin() const
	{
		return _pila1->esVacio();
	}

	template<class TElem>
	bool TSecuenciaDinamicaP<TElem>::esVacio() const
	{
		return _pila1->esVacio() && _pila2->esVacio();
	}

	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::retrocede() throw (EAccesoIndebido)
	{
		if(_pila2->esVacio())
			throw EAccesoIndebido();

		_pila1->apila(_pila2->cima());
		_pila2->desapila();
	}

	// Operaciones privadas:
	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::libera()
	{
		delete _pila1;
		delete _pila2;
	}

	template<class TElem>
	void TSecuenciaDinamicaP<TElem>::copia(const TSecuenciaDinamicaP<TElem>& secuencia)
	{
		_pila1 = new TPilaDinamica<TElem>(secuencia._pila1);
		_pila2 = new TPilaDinamica<TElem>(secuencia._pila2);
	}

	//--------------------------------------------------------

	void secAbs(TSecuenciaDinamicaP<int>&);